package com.rizzo.web.security;

import com.rizzo.back.configuration.Configuration;
import com.rizzo.back.configuration.User;
import com.rizzo.back.configuration.Users;
import com.rizzo.back.exception.ApplicationException;
import com.rizzo.web.delegator.UtilDelegator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.security.userdetails.memory.UserMap;
import org.springframework.security.userdetails.memory.UserMapEditor;
import org.springframework.util.Assert;

import java.util.Properties;

/**
 * @author Jan lievens
 */
public class XmlUserDetailsService implements UserDetailsService, InitializingBean {

    /**
     * Field utilDelegator
     */
    private UtilDelegator utilDelegator;

    /**
     * Field userMap
     */
    private UserMap userMap;

    /**
     * Method loadUserByUsername ...
     *
     * @param username of type String
     * @return UserDetails
     * @throws UsernameNotFoundException when
     * @throws DataAccessException       when
     */
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        return userMap.getUser(username);
    }

    /**
     * Method getUserMap returns the userMap of this XmlUserDetailsService object.
     *
     * @return the userMap (type UserMap) of this XmlUserDetailsService object.
     */
    public UserMap getUserMap() {
        return userMap;
    }

    /**
     * Method afterPropertiesSet ...
     *
     * @throws Exception when
     */
    public void afterPropertiesSet() throws Exception {
        try {
            // get the configured xml
            Configuration configuration = this.utilDelegator.getConfiguration();
            Properties props = new Properties();
            // get the admin and fill his details
            String adminLogin = configuration.getAdmin().getLogin();
            String adminPassword = configuration.getAdmin().getPassword();
            String adminAuthority = configuration.getAdmin().getAuthority();
            props.setProperty(adminLogin, adminPassword + "," + adminAuthority);
            // now run over all the possible users
            Users users = configuration.getUsers();
            for (User user : users.getUser()) {
                String userLogin = user.getLogin();
                String userPassword = user.getPassword();
                String userAuthority = user.getAuthority();
                props.setProperty(userLogin, userPassword + "," + userAuthority);
            }
            UserMap userMap = new UserMap();
            this.userMap = UserMapEditor.addUsersFromProperties(userMap, props);
        } catch (ApplicationException e) {
            throw new DataRetrievalFailureException("Error while accessing the configuration-xml", e);
        }
        Assert.notNull(this.userMap,
                "A list of users, passwords, enabled/disabled status and their granted authorities must be set");
    }

    /**
     * Method setUtilDelegator sets the utilDelegator of this XmlUserDetailsService object.
     *
     * @param utilDelegator the utilDelegator of this XmlUserDetailsService object.
     */
    public void setUtilDelegator(UtilDelegator utilDelegator) {
        this.utilDelegator = utilDelegator;
    }
}
